﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Engine.SceneControl;
using Engine.Physic;
using Engine.SceneControl.BrutalForceWorld;
using Engine;
using Engine.Modelo;
using Engine.Modelo.Animation;
using Engine.Input;
using Engine.Commands;
using Etapa1.BindKey;
using Engine.Features.SkyBox;
using Engine.Light;
using Engine.Behavior;
using Engine.Material.Shader;
using Etapa1.Objects;
using Engine.Physic.PhysicObjects.JigLibxObjects;
using Engine.SceneControl.Object;
using Engine.Material;
using Engine.Cameras;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Engine.MessageSystem;
using Engine.Utils.Atributes;
using Engine.SceneControl.HUD;
using Engine.Behaviors.Actions;
using Engine.Factories;
using Engine.Factories.FactoriesList.CharacterFactory;
using Engine.Factories.FactoriesList.ObjectFactory;
using Engine.Factories.FactoriesList.TerrainFactory;
using Engine.Events;
using Engine.Behaviors.Behavior;
using Etapa1.Shader;
using Engine.SceneControl.Scene;
using Microsoft.Xna.Framework.Graphics;
using Engine.SceneControl.Scene.DefRender;
using Engine.Light.Deferred;
using Engine.Features.PickingComponent;
using Engine.SceneControl.Scene.PostEffects;
using Engine.IA;
using Engine.Material.Deferred;

namespace Etapa1.Screens
{
    [Services("Engine.EngineStuff", Escopo = Escope.REQUEST)]
    public class SSAOScreen : SceneScreen
    {
        private JigLibxWorld physicWorld;
        private BrutalForceWorld mundo;
        private EngineStuff engine;
        private Manager manager;

        IObject obj = null;

        public SSAOScreen(EngineStuff es)
        {
            this.engine = es;
            engine.BackGroundColor = Color.Sienna;
            physicWorld = engine.GetManagedObject<JigLibxWorld>("Engine.Physic.JigLibxWorld");
            physicWorld.isDebugDraw = true;
            mundo = new BrutalForceWorld(physicWorld);
            manager = engine.Manager;

        }

        public override void LoadContent(Engine.EngineStuff es)
        {


            DebugVectorDraw dv = new DebugVectorDraw(engine, mundo);

            base.LoadContent(es);

            GroupedObjectsRequest gr = new GroupedObjectsRequest("..//Content//Model//Sponza", PhysicObjectTypes.TRIANGLEMESHOBJECT, Vector3.Zero, false, ShaderLib.TEXTURE);
            List<IObject> list = manager.getObject(gr) as List<IObject>;

            foreach (IObject item in list)
            {
                mundo.AddObject(item);
            }
                    

            //HeighMapRequest hmr = new HeighMapRequest("..\\Content\\Model\\terrain", ShaderLib.NORMAL_DEFERRED);
            //IObject x = manager.getObject(hmr) as IObject;
            //mundo.AddObject(x);

            //SimpleShadedObjectRequest sor2 = new SimpleShadedObjectRequest(@"..\\Content\\Model\\sphere", @"..\\Content\\Textures\\stone", PhysicObjectTypes.SPHEREOBJECT, new Vector3(50, 10, 50), true, ShaderLib.STONE);
            //IObject objx = manager.getObject(sor2) as IObject;
            //mundo.AddObject(objx);


            //SimpleModel sm2 = new SimpleModel("..\\Content\\Model\\Dsphere", "..\\Content\\Textures\\stone");
            //sm2.LoadModelo(engine.CustomContentManager);
            //ShaderLib s = new ShaderLib(engine);
            //IMaterial mat2 = new Material(s.getMaterial(ShaderLib.METAL));
            ////IMaterial mat2 = new XnaMaterial(engine);
            //IPhysicObject pi2 = new SphereObject(sm2, new Vector3(50, 10, 10), Matrix.Identity, 5);
            ////IPhysicObject pi2 = new BoxObject(sm2, new Vector3(50, 10, 10), Matrix.Identity, Vector3.One);
            //pi2.isMotionLess = true;
            //obj = new SimpleObject(null, pi2, sm2);
            //mundo.AddObject(obj);

            //for (int i = 0; i < 5; i++)
            //{                           

            //    sm2 = new SimpleModel("..\\Content\\Model\\Dsphere", "..\\Content\\Textures\\stone");
            //    sm2.LoadModelo(engine.Content);
            //    pi2 = new BoxObject(sm2, new Vector3(50, 10, 25* i), Matrix.Identity, new Vector3(2,50,2));
            //    pi2.isMotionLess = true;
            //    obj = new SimpleObject(null, pi2, sm2);
            //    mundo.AddObject(obj);

            //}


            //for (int i = 0; i < 5; i++)
            //{

            //    sm2 = new SimpleModel("..\\Content\\Model\\Dsphere", "..\\Content\\Textures\\stone");
            //    sm2.LoadModelo(engine.Content);
            //    pi2 = new BoxObject(sm2, new Vector3(25 * -i, 10,60 ), Matrix.Identity, new Vector3(2, 50, 2));
            //    pi2.isMotionLess = true;
            //    obj = new SimpleObject(null, pi2, sm2);
            //    mundo.AddObject(obj);

            //}


            //for (int i = 0; i < 5; i++)
            //{

            //    sm2 = new SimpleModel("..\\Content\\Model\\Dsphere", "..\\Content\\Textures\\stone");
            //    sm2.LoadModelo(engine.Content);
            //    pi2 = new BoxObject(sm2, new Vector3(25 * i, 10, 30 * -i), Matrix.Identity, new Vector3(2, 50, 2));
            //    pi2.isMotionLess = true;
            //    obj = new SimpleObject(null, pi2, sm2);
            //    mundo.AddObject(obj);

            //}



            /////Cria a request do Objeto Animado Complexo
            //MoveableAnimatedCharacterRequest req = new MoveableAnimatedCharacterRequest("..\\Content\\Model\\glauquinho", @"Content/CollisionInfo/gl.xml", new Vector3(0, 50, 150), "stand");

            /////Configura que tecla que desencadeia a do CharacterMovimentationBehavior
            //req.KeyToBehavior.Add(Keys.K, CharacterMovimentationBehavior.MOVEBACK);
            //req.KeyToBehavior.Add(Keys.L, CharacterMovimentationBehavior.MOVERIGHT);
            //req.KeyToBehavior.Add(Keys.J, CharacterMovimentationBehavior.MOVELEFT);
            //req.KeyToBehavior.Add(Keys.I, CharacterMovimentationBehavior.MOVEFRONT);


            /////Configura as animacoes que devem aparecer quando uma action for ativada (as actions sao ativadas pelos behaviors)
            //req.ActionToAnimation.Add(CharacterMovimentationBehavior.MOVEBACK, "walk");
            //req.ActionToAnimation.Add(CharacterMovimentationBehavior.MOVEFRONT, "walk");
            //req.ActionToAnimation.Add(CharacterMovimentationBehavior.MOVELEFT, "walk");
            //req.ActionToAnimation.Add(CharacterMovimentationBehavior.MOVERIGHT, "walk");
            //req.ActionToAnimation.Add(CharacterMovimentationBehavior.STOPPED, "stand");

            /////Cria o Objeto Animado com uso da factory 
            //IObject obb = manager.getObject(req) as IObject;
            //mundo.AddObject(obb);

            //IAgent agente = new SimpleAgent(mundo, obb);






            LightDirectional ld = new LightDirectional(new Vector3(0, -1, 0), Color.White);
            LightDirectional ld2 = new LightDirectional(new Vector3(-1, 0, -1), Color.White);
            LightDirectional ld3 = new LightDirectional(new Vector3(0, 0, 1), Color.White);
            LightDirectional ld4 = new LightDirectional(new Vector3(1, 0, 0), Color.White);
            mundo.AddLight(ld);
            mundo.AddLight(ld2);
            mundo.AddLight(ld3);
            mundo.AddLight(ld4);


            //LightPoint lp = new LightPoint(new Vector3(50, 10, 50), Color.Red, 100, 1);
            //mundo.AddLight(lp);

            //LightPoint lp2 = new LightPoint(new Vector3(-50, 10, -10), Color.Black, 50, 20);
            //mundo.AddLight(lp2);


            //CameraPrimeiraPessoa cam = new CameraPrimeiraPessoa(engine.GraphicsDevice.Viewport);
            //StaticCamera cam = new StaticCamera(new Vector3(0, 50, 0), new Vector3(0, 49, 0));

            //Vector3 dir = new Vector3(-0.30f, -0.7f, -0.4f);
            //Vector3 pos = new Vector3(10, 150, 10);
            ////dir.Normalize();
            //SpotLight sl2 = new MoveableSpotLight(pos, dir, 0.5f, 500f, Color.Red, (float)Math.Cos(Math.PI / 10), 15f);
            ////SpotLight sl2 = new MoveableSpotLight(cam.Position, new Vector3(0, -1, 0) , 0.5f, 500f, Color.Red, (float)Math.Cos(Math.PI / 12), 15f);
            //mundo.AddLight(sl2);
            //lightControler l = new lightControler(sl2.getId());


            ICamera cam;//= new StaticCamera(pos,dir);
            //sl2.ProjMatrix = cam.Projection;
            //sl2.ViewMatrix = cam.View;

            cam = new CameraPrimeiraPessoa(engine.GraphicsDevice.Viewport);

            Vector3 dir2 = new Vector3(-0.3f, -0.7f, -0.4f);
            dir2.Normalize();
            SpotLight sl4 = new SpotLight(new Vector3(100, 50, 0), dir2, 1f, 10000f, Color.White, (float)Math.Cos(Math.PI / 3), 1f);
            mundo.AddLight(sl4);




            ////Criacao de uma Tecnica
            BasicDeferredRenderTechnic dr = new BasicDeferredRenderTechnic(engine);
            //dr.DeferredLightMap = new ShadowLightMap();            
            //dr.isPhysicDebug = true;
            dr.isDebug = false;
            //dr.PostEffectList.Add(new ToonPostEffect());            
            //dr.PostEffectList.Add(new DephtOfFieldPostEffect());            
            //dr.PostEffectList.Add(new NoisePostEffect());
            //dr.PostEffectList.Add(new BlurPostEffect());
            //dr.PostEffectList.Add(new BlurPostEffect());
            //dr.PostEffectList.Add(new GaussianBlurPostEffect());
            //dr.PostEffectList.Add(new WigglePostEffect());

            //CircularGlowPostEffect gl = new CircularGlowPostEffect();
            //gl.GlowExtraSize = 20;
            //gl.SetGlowObjects(new IObject[] { obj });
            //dr.PostEffectList.Add(gl);

            IRenderTechnic[] rt = new IRenderTechnic[] { dr };

            this.RenderTechnics = rt;

            mundo.AddCamera(cam);
            this.World = mundo;

            BindThrow bt = new BindThrow(World, cam, engine, false);

            //updateTeste ut = new updateTeste(engine);

            //engine.AddComponent("Picking");
            //PickingParameters pp = new PickingParameters(cam, World,MouseButtons.LeftButton);
            //SimpleObserver o1 =  new SimpleObserver();
            //SimpleObserver o2 = new SimpleObserver();
            //pp.Observers.Add(o1);
            //pp.Observers.Add(o2);
            //CommandProcessor.getCommandProcessor().SendCommandSyncronous(pp);

            SkyBoxUpdateParametersCommand sc = new SkyBoxUpdateParametersCommand(cam);
            engine.AddComponent(sc);

            //PickingRemove pr = new PickingRemove(MouseButtons.LeftButton);
            //pr.Observers.Add(o1);
            //CommandProcessor.getCommandProcessor().SendCommandSyncronous(pr);

        }



    }
}
